package com.yeskery.nut.extend.mcp.server.method;

import com.yeskery.nut.bean.ApplicationContext;
import com.yeskery.nut.extend.mcp.annotation.McpPromptProperty;
import com.yeskery.nut.extend.mcp.core.ExecuteExceptionHandler;
import com.yeskery.nut.extend.mcp.core.JsonMessage;
import com.yeskery.nut.extend.mcp.core.JsonResponse;
import com.yeskery.nut.extend.mcp.core.schema.ContentSchema;
import com.yeskery.nut.extend.mcp.core.schema.PromptSchema;
import com.yeskery.nut.extend.mcp.core.schema.Role;
import com.yeskery.nut.extend.mcp.server.McpExecuteMetadata;
import com.yeskery.nut.extend.mcp.server.McpServerCapability;
import com.yeskery.nut.extend.mcp.server.McpToolMetadata;
import com.yeskery.nut.util.BeanUtils;
import com.yeskery.nut.util.StringUtils;

import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 提示获取方法处理器
 * @author sprout
 * 2025-05-06 14:56
 */
public class PromptsGetMethodHandler extends BaseCallMethodHandler {
    /**
     * 构造提示获取方法处理器
     * @param applicationContext  应用上下文
     * @param mcpServerCapability 服务能力
     */
    public PromptsGetMethodHandler(ApplicationContext applicationContext, McpServerCapability mcpServerCapability) {
        super(applicationContext, mcpServerCapability);
    }

    @Override
    protected Object getCallRequest(JsonMessage jsonMessage) {
        return getJsonRequestObject(jsonMessage, PromptSchema.GetPromptRequest.class);
    }

    @Override
    protected Map<String, Object> getCallRequestArguments(Object request) {
        return ((PromptSchema.GetPromptRequest) request).getArguments();
    }

    @Override
    protected McpExecuteMetadata getCallRequestMetadata(Object request) {
        return getMcpServerCapability().getMcpPromptMetadata(((PromptSchema.GetPromptRequest) request).getName());
    }

    @Override
    protected String getParameterName(Parameter parameter) {
        McpPromptProperty mcpPromptProperty = parameter.getAnnotation(McpPromptProperty.class);
        return getParameterName(parameter, mcpPromptProperty);
    }

    @Override
    protected boolean isParameterRequired(Parameter parameter) {
        McpPromptProperty mcpPromptProperty = parameter.getAnnotation(McpPromptProperty.class);
        return isParameterRequired(mcpPromptProperty);
    }

    @Override
    protected void handleResponse(McpExecuteMetadata callRequestMetadata, Object callRequest, Type returnType, Object invokeResult, JsonResponse jsonResponse) {
        if (BeanUtils.getDependBeanType(returnType).equals(PromptSchema.GetPromptResult.class)) {
            jsonResponse.setResult(invokeResult);
            return;
        }
        List<ContentSchema.Content> contents = getInvokeResultContent(returnType, invokeResult);
        List<PromptSchema.PromptMessage> promptMessages = new ArrayList<>(contents.size());
        for (ContentSchema.Content content : contents) {
            PromptSchema.PromptMessage promptMessage = new PromptSchema.PromptMessage();
            promptMessage.setRole(Role.USER);
            promptMessage.setContent(content);
            promptMessages.add(promptMessage);
        }

        PromptSchema.GetPromptResult result = new PromptSchema.GetPromptResult();
        result.setMessages(promptMessages);
        jsonResponse.setResult(result);
    }

    @Override
    protected ExecuteExceptionHandler getExecuteExceptionHandler(McpExecuteMetadata callRequestMetadata, Object callRequest) {
        return ((McpToolMetadata) callRequestMetadata).getTool().getExceptionHandler();
    }

    @Override
    protected String getDefaultExceptionMessage(Exception e, McpExecuteMetadata callRequestMetadata, Object callRequest) {
        return "Tool [" + ((PromptSchema.GetPromptRequest) callRequest).getName() + "] Invoke Fail.";
    }

    /**
     * 获取参数名称
     * @param parameter 参数
     * @param mcpPromptProperty 注解
     * @return 参数名称
     */
    private String getParameterName(Parameter parameter, McpPromptProperty mcpPromptProperty) {
        String name = parameter.getName();
        if (mcpPromptProperty != null && !StringUtils.isBlank(mcpPromptProperty.value())) {
            name = mcpPromptProperty.value();
        }
        return name;
    }

    /**
     * 判断参数是否必填
     * @param mcpPromptProperty 注解
     * @return 是否必填
     */
    private boolean isParameterRequired(McpPromptProperty mcpPromptProperty) {
        boolean required = true;
        if (mcpPromptProperty != null) {
            required = mcpPromptProperty.required();
        }
        return required;
    }
}
